<html>
  <head>
    <title>条件编译处理多端差异</title>
  </head>
  <body>
    <script>
      /*
           ★、为什么选择条件编译处理跨端兼容？


                    uni-app已将常用的组件、API封装到框架中，开发者按照uni-app规范开发即可保证多平台兼容，

                    大部分业务均可直接满足。


                    但每个平台有自己的一些特性，因此会存在一些无法跨平台的情况：

                        1、大量编写 if else ,会造成代码执行性能低下和管理混乱。

                        2、编译到不同的工程后二次修改，会让后续升级变的很麻烦。

                        3、为每个平台重写，明明主业务逻辑又一样。

                   在C语言中，通过 #ifdef、#ifndef 的方式，为 windows 、Mac 等不同OS编译不同的代码。

                   uni-app 团队参考这个思路，为 uni-app 提供了条件编译手段，在一个工程里优雅的完成了平台个性化实现。
      */

      /*
            条件编译

                条件编译时用特殊的注释作为标记，在编译时根据这些特殊的注释，将注释里的代码编译到不同平台中。


                一、使用方法

                       以 #ifdef 或 #ifndef 加 %PLATFORM% 开头，以 #endif结尾

                       ①、 #ifdef ： if defined  仅在某平台存在

                       ②、#ifndef:  if not defined 除了某平台均存在

                       ③、%PLATFORM%： 平台名称



                       条件编译写法                             说明

                       #ifdef APP-PLUS
                          --需条件编译的代码--                  仅出现在App平台下的代码
                       #endif


                       #ifndef H5
                          --需要条件编译的代码--                除了H5平台，其他平台均存在的代码 (注意 if 后面有个n)
                       #endif 

                              1、%PLATFORM%

                                        值                       生效条件                                   
                                        
                                        VUE3                     uni-app js引擎版用于区分vue2和3，详情

                                        VUE2                     uni-app js引擎版用于区分vue2和3，详情

                                        UNI-APP-X                用于区分是否是uni-app x项目 详情

                                        uniVersion               用于区分编译器的版本 详情

                                        APP                      APP

                                        APP-PLUS                 uni-app js引擎版编译为App时

                                        APP-PLUS-NVUE
                                        或                        App nvue 页面
                                        APP-NVUE  

                                        APP-ANDROID               App Android 平台 详情

                                        APP-IOS                   App iOS 平台 详情

                                        APP-HARMONY               App HarmonyOS Next 平台

                                        H5                        H5（推荐使用 WEB）

                                        WEB                        web（同H5）

                                        MP-WEIXIN                  微信小程序
                                        
                                        MP-ALIPAY                  支付宝小程序

                                        MP-BAIDU                   百度小程序

                                        MP-TOUTIAO                 头条小程序

                                        MP-LARK                    飞书小程序

                                        MP-QQ                      QQ小程序

                                        MP-KUAISHOU                快手小程序

                                        MP-JD                      京东小程序
                                        
                                        MP-360                      360小程序           

                                        MP-HARMONY                 鸿蒙元服务

                                        MP-XHS                     小红书小程序

                                        MP                        微信小程序/支付宝小程序/百度小程序/抖音小程序/飞书小程序/QQ小程序/360小程序/鸿蒙元服务

                                        QUICKAPP-WEBVIEW           快应用通用(包含联盟、华为)

                                        QUICKAPP-WEBVIEW-UNION     快应用联盟

                                        QUICKAPP-WEBVIEW-HUAWEI    快应用华为


                                2、支持的文件

                                          ①、 .vue  、.nvue  、 .uvue

                                          ②、 .js  、 .uts

                                          ③、 .css

                                          ④、 pages.json

                                          ⑤、 各预编译语言文件，  如：  .scss 、 .less 、  .stylus 、 .ts  、 .pug

                                    注意：
                                    
                                          ①、条件编译时利用注释实现的，在不同的语法里注释写法不一样，
                                              js/uts 使用 "//"" 注释、
                                              
                                              css 使用 "/*"  注释

                                              vue/nvue/uvue模板里使用"<!--"注释

                                          ②、条件编译 App-plus 包含 APP-NVUE 和  APP-vue，APP-PLUS-NVUE和APP-NVUE没什么区别，为了简写后面出了APP-NVUE ；

                                          ③、对于未定义平台名称，可能是名称写错了，也可能是低版本HBuilderX还不认识这个平台。

                                                此时的条件编译， #ifdef 中的代码不会生效， 而  #ifndef 中的代码会生效；

                                          ④、使用条件编译请保证  "编译前" 和 "编译后" 文件的语法正确，即要保障无论条件编译时否生效都能通过语法校验。

                                                比如： json 文件中不能有多余的逗号，js中不能重复导入：

                                                    json错误示例:
                                                            {
                                                              "key": "a",
                                                              // #ifdef MP-WEIXIN
                                                              "key": "b"
                                                              // #endif
                                                            }

                                                      json正确示例：
                                                            {
                                                              "key": "a"
                                                              // #ifdef MP-WEIXIN
                                                              ,"key": "b"
                                                              // #endif
                                                            }

                                                      js错误示例：
                                                            // #ifdef MP-WEIXIN
                                                            import a from 'a/wx'
                                                            // #endif
                                                            // #ifndef MP-WEIXIN
                                                            import a from 'a/index'
                                                            // #endif

                                                      js正确示例：
                                                            // #ifdef MP-WEIXIN
                                                            import a as aWx from 'a/wx'
                                                            // #endif
                                                            // #ifndef MP-WEIXIN
                                                            import a as aIndex from 'a/index'
                                                            // #endif
                                                            var a
                                                            // #ifdef MP-WEIXIN
                                                            a = aWx
                                                            // #endif
                                                            // #ifndef MP-WEIXIN
                                                            a = aIndex
                                                            // #endif
      */

      /*
            二、API的条件编译

                        // #ifdef  %PLATFORM%
                          平台特有的API实现
                        // #endif 
                        
                    
                     1、 示例，如下代码仅在App下实现：

                                //#ifdef APP-PLUS
                                  plus.push.addEventListener('click',function(msg){
                                                  
                                  })
                                //#endif

                     2、 实例，如下代码不会在H5平台上出现

                                //#ifndef H5
                                  uni.scanCode({
                                      successs:res=>{
                                                  console.log(res)
                                      }
                                  })
                                //#endif

                     3、 除了支持单个平台的条件编译外，还支持"多平台"同时编译，使用 "||"来分隔平台名称。

                      eg：   如下代码会在App 和 H5平台上出现

                              //#ifdef APP-PLUS || H5
                                 uni.chooseVideo({
                                    success:res=>{
                                        console.log(res.result)
                                    }
                                 });
                               //#endif                
      */

      /*
           三、组件的条件编译

                      <!- #ifdef  %PLATFORM%  ->
                          平台特有的组件
                      <!- #endif->

                      1、示例，  如下公众号关注组件仅会在微信小程序中出现：

                                  <view>
                                      <view>微信公众号关注组件</view>
                                      <view>
                                          <!-- uni-app未封装，但可直接使用微信原生的official-account组件->
                                          <!-- #ifdef MP-WEIXIN ->
                                              <official-account></official-account>
                                          <!-- #endif ->
                                      </view>
                                  </view>    
      */

      /*
           四、样式的条件编译

                        /*  #ifdef  %PLATFORM%  *
                          平台特有样式
                        /*  #endif  *

                        注意：  样式的条件编译，无论是css 还是 sass、scss、less、stylus 等预编译语言中，必须使用 "/*"的写法。
      */

      /*
          五、pages.json 的条件编译

                     下面的页面，只有运行至 App 时才会编译进去。
                     
                                // #ifdef APP-PLUS
                                  {
                                    "path":"pages/api/speech/speech",
                                    "style":{
                                        "navigationBarTitileText":"语音识别"
                                    }
                                  }
                                // #endif

                      不同平台下的特有功能，以及小程序平台的分包，都可以通过 pages.json 的条件编译来更好的实现。

                      这样就不会再其他平台产生多余的资源，进而减小包体积。

                      json的条件编译，如不同平台的key名称相同，cli项目下开发者自己安装的校验器会报错，
                      
                      需要自行关闭这些校验器对json相同key的校验规则。如果使用HBuilderX的校验器，无需在意此问题，

                      HBuilderX的语法校验器为此优化过。
      */

      /*
          六、static 目录的条件编译

                      这里也解释了 static 内的哪些目录是特殊的。

                      在不同平台，引用的静态资源可能也存在差异，通过 static 的条件编译可以解决此问题，

                      static目录下新建不同平台的专有目录，目录名称均为 "小写"

                                  目录名                   说明  
                                  
                                  app-plus                 app（推荐使用app）

                                  app-harmony              HarmonyOS Next

                                  app                      app

                                  h5                       H5（推荐使用web）

                                  web                      web

                                  mp-weixin                微信小程序

                                  mp-alipay                支付宝小程序

                                  mp-baidu                 百度小程序

                                  mp-qq                    qq小程序

                                  mp-toutiao               抖音头条小程序

                                  mp-lark                  飞书小程序

                                  mp-kuaishou              快手小程序

                                  mp-jd                    京东小程序

                                  mp-360                   360小程序

                                  mp-huawei                华为小程序

                                  mp-xhs                   小红书小程序

                                  mp-kunlun                快手小程序


                       专有目录下的静态资源只有在特定平台才会编译进去。

                       如以下目录结构， a.png 只有在微信小程序平台才会被编译进去， b.png 在所有平台都会被编译。

                                  ┌─static
                                  │  ├─mp-weixin
                                  │  │  └─a.png
                                  │  └─b.png
                                  ├─main.js
                                  ├─App.vue
                                  ├─manifest.json
                                  └─pages.json

                      注意：
                                
                           ①、自HBuliderX 3.9+起，App平台static 目录同时支持 app、app-plus 目录， web平台static目录同时支持web、h5目录。

                           
                           ②、自HBuilderX3.98+起，编译时增加 static 下被忽略的非当前平台专有目录提示信息，
                           
                              如static下同时存在app、web，运行到web时，会提示static/app已被忽略
      */

      /*
           七、整体目录条件编译

                      如果想把各平台的页面文件更彻底的分开， 也可以在uni-app项目根目录创建platforms目录，

                      然后在下面进一步创建app-plus、mp-weixin等子目录，存放不同平台的文件。

                      注意：

                            platforms 目录下只支持防止页面文件(即页面 vue 文件)，如果需要对其他资源条件编译，

                            建议使用static 目录的条件编译。
      */

      /*
           八、uts的条件编译

                      对于 APP-ANDROID 和 APP——IOS两个平台，

                          ①、在uni-app项目中，仅uts文件中支持（通常是uts插件里使用）

                          ②、在uni-app x项目中，只要是条件编译支持的文件，均可以使用


                          eg:

                                  // #ifdef  %PLATFORM%
                                    平台特有的API实现
                                  // #endif
      */

      /*
           九、 uni-app x 项目的条件编译

                      使用 UNI-APP-X条件编译，来区分 uni-app x 项目和 uni-app 项目。


      */

      /*
           十、HBuildX支持

                     HBuilderX 为 uni-app 的条件编译提供了丰富的支持:
                     
                     1、代码块支持
                                  
                                在 HBuilderX 中开发 uni-app 时，通过输入 ifdef 可快速生成条件编译的代码片段：
                                
                                https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/uni-022402.png

                     2、语法高亮

                                在HBuilderX 中对条件编译的代码注释部分提供了语法高亮，可分辨出写法是否正确，
                                
                          使得代码更加清晰 (独立js文件需在编译器右下角切换javascript es6+编辑器，独立css文件暂不支持高亮，但不高亮不影响使用)

                     3、正确注释和快速选中

                               在 HBuilderX中， ctrl+alt+/ 即可生成正确注释 .(根据文件类型生成正确注释)

                               https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/uni2019012801.png

                               点击 ifdef 或 endif 可快速选中条件编译部分；点击左侧的折叠图标，可折叠条件编译部分代码。

                               https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/uni-012501.png
      */

      /*
           十一、注意


                 ①、  Android 和 ios平台不支持通过条件编译来区分，如果需要区分 Android、ios平台，

                      请通过调用 uni.getSystemInfo来获取品台信息。。

                      支持 ifios 、 ifAndroid 代码块，可方便编写判断

                 ②、 有些跨端工具可以提供js的条件编译或多态，单着对于实际开发远远不够。

                     uni-app不止是处理js，任何代码都可以多端条件编译，才能真正解决实际项目的跨端问题。

                     另外，所谓多态在实际开发中会造成大量冗余代码，很不利于复用和维护。

                     举例，微信小程序主题颜色时绿色，二报读支付宝小程序时蓝色，你的应用想分平台适配颜色，

                     只有条件编译时代码量最低、最容易维护的。

                 ③、有些公司的产品运营总是给不同平台提不同需求，但这不是拒绝uni-app 的理由。

                    关键在于项目里，复用的代码多还是个性的代码多，正常都是复用的代码多，所以仍然应该多端。

                    而个性的代码放到不同的平台目录下，差异化维护。
      */
      
    </script>
  </body>
</html>